home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw / OffSample / UFailure.inc1.p < prev    next >
Encoding:
Text File  |  2000-09-28  |  9.0 KB  |  391 lines  |  [TEXT/MPS ]

  1. {------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    Exception handling for MPW Pascal, MacApp and MPW C
  6. #
  7. #    UFailure (aka Signals) - “Exceptional code, with a few exceptions.”
  8. #
  9. #    UFailure.inc1.p    -    Pascal source - the IMPLEMENTATION
  10. #
  11. #    Copyright © 1985-1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.0                    11/88
  15. #
  16. #    Components:    UFailure.p            November 1, 1988
  17. #                UFailure.h            November 1, 1988
  18. #                UFailure.inc1.p        November 1, 1988
  19. #                UFailure.a            November 1, 1988
  20. #
  21. #    UFailure (or Signals) is a set of exception handling routines suitable for
  22. #    use with MacApp, MPW C, and MPW Pascal. It is a jazzed-up version of the MacApp
  23. #    UFailure unit. There is a set of C interfaces to it as well.
  24. #
  25. ------------------------------------------------------------------------------}
  26.  
  27.  
  28. VAR
  29.     {$PUSH}
  30.     {$Z+}    {make gTopHandler accessable to assembly code}
  31.     gTopHandler:        PFailInfo;    {linked list of failure handlers}
  32.      gInitHandler:        ProcPtr;
  33.     {$POP}
  34.  
  35.  
  36. PROCEDURE InitUFailure; EXTERNAL;
  37.     { Allocates the heap block for CatchSignals and initializes the global
  38.         variables used by the unit. }
  39.  
  40. PROCEDURE InitSignals; EXTERNAL;
  41.     { Calls InitUFailure. It also sets up the A6 for the main level of Pascal,
  42.         so it must be called from the outermost level of Pascal. }
  43.  
  44.  
  45. FUNCTION CatchSignal: INTEGER; EXTERNAL;
  46.     { Until the procedure which encloses this call returns, this will catch
  47.         subsequent Signal calls, returning the code passed to Signal.  When
  48.         CatchSignal is encountered initially, it returns a code of zero.  These
  49.         calls may "nest"; i.e. you may have multiple CatchSignals in one procedure.
  50.         Each nested CatchSignal call uses 72 bytes of heap space.
  51.         If you signal with SignalMessage and pass in a non-zero message you should use
  52.         CatchHandler instead so you have a way of getting at the message. }
  53.  
  54.  
  55. PROCEDURE FreeSignal; EXTERNAL;
  56.     { This undoes the effect of the last CatchSignal.  A Signal will then invoke
  57.         the CatchSignal prior to the last one. }
  58.  
  59.  
  60. PROCEDURE Signal(code: INTEGER); EXTERNAL;
  61.     { Returns control to the point of the last CatchSignal.  The program will
  62.         then behave as though that CatchSignal had returned with the code parameter
  63.         supplied to Signal. If CatchHandler is catching, the message parameter will be 0. }
  64.  
  65.  
  66. PROCEDURE SignalMessage(code: INTEGER; message: LONGINT); EXTERNAL;
  67.     { Returns control to the point of the last CatchSignal/CatchFailures.
  68.         If CatchFailures is catching, the message parameter will be returned. }
  69.         
  70.         
  71. {-----------------------------------+
  72. |    MacApp stuff                    |
  73. +-----------------------------------}
  74.  
  75.  
  76. {-----------------------------------+ 
  77. |    External Declarations            |
  78. +-----------------------------------}
  79. PROCEDURE CatchFailures (VAR fi: FailInfo;
  80.                         PROCEDURE Handler(e: INTEGER; m: LONGINT)); EXTERNAL;
  81.  
  82. PROCEDURE DoFailure(pf: PFailInfo); EXTERNAL;
  83.  
  84. {-----------------------------------+ 
  85. |    CallInitHandler                    |
  86. +-----------------------------------}
  87. PROCEDURE CallInitHandler (error: INTEGER; message: LONGINT; p: ProcPtr);
  88.         INLINE    $205F,        {MOVE.L        (A7)+,A0    }
  89.                 $4E90;        {JMP        (A0)        }
  90.  
  91. {$IFC UsingMacApp}
  92. {$S MAMain}
  93. {$ENDC}
  94. {-----------------------------------+ 
  95. |    FailMemError                    |
  96. +-----------------------------------}
  97. PROCEDURE FailMemError;
  98. VAR
  99.     e:    OSErr;
  100. {$IFC qDebug}
  101.     s:        Str255;
  102. {$ENDC}
  103. BEGIN
  104.     e := MemError;
  105.  
  106. {$IFC UsingMacApp}
  107. {$IFC qDebug}
  108.     IF gAskFailure AND (e = noErr) AND CanReadLn THEN
  109.         BEGIN
  110. {$%+}
  111.         GetMethodName(%_GetA6+4, s);
  112. {$%-}
  113.         e := ReadInteger(CONCAT('FailMemError called by ', s, '.  Enter return error: '));
  114.         END;
  115. {$ENDC qDebug}
  116. {$ENDC UsingMacApp}
  117.  
  118.     IF e <> noErr THEN
  119.         Failure(e, 0);
  120. END {FailMemError};
  121.  
  122.  
  123. {$IFC UsingMacApp}
  124. {$S MAMain}
  125. {$ENDC}
  126. {-----------------------------------+ 
  127. |    FailNIL                            |
  128. +-----------------------------------}
  129. PROCEDURE FailNIL (p: UNIV Ptr);
  130. BEGIN
  131.     { no check for gAskFailure here, since we do this when objects are created. }
  132.     IF p = NIL THEN
  133.         Failure(memFullErr, 0);
  134. END {FailNIL};
  135.  
  136.  
  137. {$IFC UsingMacApp}
  138. {$S MAMain}
  139. {$ENDC}
  140. {-----------------------------------+ 
  141. |    FailNewMessage                    |
  142. +-----------------------------------}
  143. PROCEDURE FailNewMessage (error: INTEGER; oldMessage, newMessage: LONGINT);
  144. BEGIN
  145.     IF oldMessage = 0 THEN
  146.         oldMessage := newMessage;
  147.     Failure(error, oldMessage);
  148. END {FailNewMessage};
  149.  
  150.  
  151. {$IFC UsingMacApp}
  152. {$S MAMain}
  153. {$ENDC}
  154. {-----------------------------------+ 
  155. |    FailOSErr                        |
  156. +-----------------------------------}
  157. PROCEDURE FailOSErr (error: INTEGER);
  158.  
  159. {$IFC qDebug}
  160. VAR
  161.     s:        Str255;
  162. {$ENDC}
  163.  
  164. BEGIN
  165. {$IFC UsingMacApp}
  166. {$IFC qDebug}
  167.     IF gAskFailure AND (error = noErr) AND CanReadLn THEN
  168.         BEGIN
  169. {$%+}
  170.         GetMethodName(%_GetA6+4, s);
  171. {$%-}
  172.         error := ReadInteger(CONCAT('FailOSErr called by ', s, '.  Enter return error: '));
  173.         END;
  174. {$ENDC qDebug}
  175. {$ENDC UsingMacApp}
  176.  
  177.     IF error <> noErr THEN
  178.         Failure(error, 0);
  179. END {FailOSErr};
  180.  
  181.  
  182. {$IFC UsingMacApp}
  183. {$S MAMain}
  184. {$ENDC}
  185. {-----------------------------------+ 
  186. |    FailResError                    |
  187. +-----------------------------------}
  188. PROCEDURE FailResError;
  189. VAR
  190.     e:    OSErr;
  191. {$IFC qDebug}
  192.     s:        Str255;
  193. {$ENDC}
  194. BEGIN
  195.     e := ResError;
  196.  
  197. {$IFC UsingMacApp}
  198. {$IFC qDebug}
  199.     IF gAskFailure AND (e = noErr) AND CanReadLn THEN
  200.         BEGIN
  201. {$%+}
  202.         GetMethodName(%_GetA6+4, s);
  203. {$%-}
  204.         e := ReadInteger(CONCAT('FailResError called by ', s, '.  Enter return error: '));
  205.         END;
  206. {$ENDC qDebug}
  207. {$ENDC UsingMacApp}
  208.  
  209.     IF e <> noErr THEN
  210.         Failure(e, 0);
  211. END {FailResError};
  212.  
  213.  
  214. {$IFC UsingMacApp}
  215. {$S MAMain}
  216. {$ENDC}
  217. {-----------------------------------+ 
  218. |    Failure                            |
  219. +-----------------------------------}
  220. PROCEDURE Failure (error: INTEGER; message: LONGINT);
  221. VAR
  222.     pf:     PFailInfo;
  223.     ih:     ProcPtr;
  224.     pc:        LONGINT;
  225. {$IFC UsingMacApp}
  226. {$IFC qDebug}
  227.     cl:     String8;
  228.     me:     String8;
  229.     seg:    INTEGER;
  230.     who:    STRING[17];
  231. {$ENDC qDebug}
  232. {$ENDC UsingMacApp}
  233. BEGIN
  234.     pf := gTopHandler;
  235.  
  236.     IF pf <> NIL THEN
  237.         BEGIN
  238. {$IFC UsingMacApp}
  239. {$IFC qDebug}
  240.         pc := pf^.whoPC;
  241.         GetProcname(LONGINT(@pc), cl, me);
  242.         who := CONCAT(cl, '.', me);
  243.         IF cl = kSpace8 THEN
  244.             who[9] := ' ';
  245.         
  246.         Writeln('Failure caught by ', who);
  247.         Writeln('        error = ', error:1, ' message = ', message:1,
  248.                 ' (', BSR(message, 16):1, '/', BAND(message, $0000FFFF):1, ')');
  249. {$ENDC qDebug}
  250. {$ENDC UsingMacApp}
  251.  
  252.     {* RBB removed the line 
  253.         gTopHandler := pf^.nextInfo;
  254.       on 9/26/88 since DoFailure calls FreeSignal first thing *}
  255.         pf^.error := error;
  256.         pf^.message := message;
  257.         DoFailure(pf);            {Go execute the failure handler}
  258.         END
  259.     ELSE IF gInitHandler <> NIL THEN
  260.         BEGIN
  261.         ih := gInitHandler;
  262.         gInitHandler := NIL;
  263.         CallInitHandler(error, message, ih);
  264.  
  265.         ExitToShell;
  266.         END
  267.     ELSE
  268.         BEGIN
  269. {$IFC UsingMacApp}
  270. {$IFC qDebug}
  271.         ProgramBreak('Failure called, but no handler!');
  272. {$ENDC qDebug}
  273. {$ELSEC}
  274.     Debugger;
  275. {$ENDC UsingMacApp}
  276.         END;
  277. END {Failure};
  278.  
  279.  
  280. {$IFC UsingMacApp}
  281. {$IFC qDebug}
  282. {$IFC qTrace}{$D+}{$ENDC}
  283. {$S MADebug}
  284. {-----------------------------------+ 
  285. |    ProgramBreak                    |
  286. +-----------------------------------}
  287. PROCEDURE ProgramBreak (grievance: Str255);
  288.     { ProgramBreak: Your app can call this when it comes to a situation that you do not expect
  289.         and cannot handle gracefully.  It beeps and displays a message.  If called before
  290.         there is a WriteLn window, it calls OBJFail, which goes into an infinite loop.
  291.         Otherwise, it enters our debugger. }
  292. VAR
  293.     synthRec:    RECORD
  294.                 mode:        INTEGER;
  295.                 triplet:    Tone;
  296.                 endTriplet: Tone;
  297.                 END;
  298.  
  299. BEGIN
  300. {$IFC FALSE}
  301.     WITH synthRec, triplet DO
  302.         BEGIN
  303.         mode := swMode;
  304.  
  305.         count := 445;
  306.         amplitude := 100;
  307.         duration := 25;
  308.  
  309.         endTriplet.count := 0;
  310.         endTriplet.amplitude := 0;
  311.         endTriplet.duration := 0;
  312.         END;
  313.  
  314.     StartSound(@synthRec, SIZEOF(synthRec), Pointer(-1));
  315. {$ENDC}
  316.     SysBeep(2);
  317.  
  318.     WWForceOutput(forceOn, forceUnchanged);
  319.     WriteLn('ProgramBreak: ', grievance);
  320.     WWEndForce;
  321.  
  322. {$IFC qTrace}
  323.     TRCBreak;
  324. {$ELSEC}
  325.     OBJFail(kFailNone);
  326. {$ENDC}
  327. END {ProgramBreak};
  328. {$IFC qTrace}{$D++}{$ENDC}
  329.  
  330.  
  331. {$IFC qTrace}{$D+}{$ENDC}
  332. {$S MADebug}
  333. {-----------------------------------+ 
  334. |    ProgramReport                    |
  335. +-----------------------------------}
  336. PROCEDURE ProgramReport (grievance: Str255; break: BOOLEAN);
  337.  
  338. BEGIN
  339.     Writeln(grievance);
  340.     IF break THEN
  341.         TRCBreak;
  342. END {ProgramReport};
  343. {$IFC qTrace}{$D++}{$ENDC}
  344. {$ENDC qDebug}
  345. {$ENDC UsingMacApp}
  346.  
  347.  
  348. {$IFC UsingMacApp}
  349. {$S MAInit}
  350. {$IFC qTrace}{$D+}{$ENDC}
  351. {-----------------------------------+ 
  352. |    SetInitHandler                    |
  353. +-----------------------------------}
  354. PROCEDURE SetInitHandler (handler: ProcPtr);
  355. BEGIN
  356.     gInitHandler := handler;
  357. END {SetInitHandler};
  358. {$IFC qTrace}{$D++}{$ENDC}
  359. {$ENDC UsingMacApp}
  360.  
  361.  
  362. {We assume that the programmer passes in the correct FailInfo record; ie. the one that is the
  363.     top of the stack.}
  364. {$IFC UsingMacApp}
  365. {$S MAMain}
  366. {$ENDC}
  367. {-----------------------------------+ 
  368. |    Success                            |
  369. +-----------------------------------}
  370. PROCEDURE Success (VAR fi: FailInfo);
  371. BEGIN
  372. {$IFC qDebug}
  373.     IF gTopHandler <> @fi THEN
  374.     {$IFC UsingMacApp}
  375.         BEGIN
  376.         Write('gTopHandler = ');
  377.         WritePtr(gTopHandler);
  378.         Write('parameter = ');
  379.         WritePtr(@fi);
  380.         WRITELN;
  381.         ProgramBreak('Problem with Success: too many or too few calls to Success');
  382.         END;
  383.     {$ELSEC UsingMacApp}
  384.         Debugger;
  385.     {$ENDC UsingMacApp}
  386. {$ENDC qDebug}
  387.  
  388.     gTopHandler := fi.nextInfo;
  389. END {Success};
  390.  
  391.